package com.wolf.etl.core.dialect;

import com.wolf.etl.core.JoinManager;
import com.wolf.etl.core.rule.TransformRuleManager;
import com.wolf.etl.model.*;
import com.wolf.etl.vo.BuildSqlParam;
import com.wolf.etl.vo.ColumnDesc;
import com.wolf.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

/**
 * @author sdyang
 * @create 2019-06-13 11:36
 **/
@Service("oracleDialect")
public class OracleDialect extends AbstractDialect {

    private static Logger logger = LoggerFactory.getLogger(OracleDialect.class);

    private static final String logger_prefix = "wolf-etl#com.wolf.etl.core.dialect#OracleDialect";

    private static final String LEFT_JOIN = " left join ";

    @Override
    public String buildPaginationSql(String originalSql, int offset, int limit) {
        limit = (offset >= 1) ? (offset + limit) : limit;
        String sql = "SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( %s ) TMP WHERE ROWNUM <=%s) WHERE ROW_ID > %s";
        return String.format(sql, originalSql, limit, offset);
    }

    @Override
    public String buildSelect(BuildSqlParam param) {
        StringBuffer sql = new StringBuffer();

        int length = 0;
        for (EtlTransformDefineModel transform : param.getTransformDefineModelList()) {

            String field = getFieldWithPrefix(param.getAliasMap().get(transform.getSrc_table_id()), transform.getSrc_column_name());

            field = TransformRuleManager.getInstance(manager,param).execSource(field,transform.getId());

            sql.append(field).append(" ");

            if (StringUtils.isNotEmpty(transform.getSrc_column_alias())) {
                sql.append(transform.getSrc_column_alias());
            }
            if (length != param.getTransformDefineModelList().size() - 1) {
                sql.append(COMMA);
            }
            length++;
        }


        // join语句
        int i = 0;
        StringBuffer relSql = new StringBuffer();
        JoinManager joinManager = JoinManager.getInstance(manager, param);
        for (EtlTableRelModel rel : param.getRels()) {

            // 检查字段关联合法性
            joinManager.check(this, rel);

            String masterTable = String.format(FORMAT_TABLE_ALIAS, param.getRelMap().get(rel.getMaster_table_id()).getName(), param.getAliasMap().get(rel.getMaster_table_id()));

            String slaveTable = String.format(FORMAT_TABLE_ALIAS, param.getRelMap().get(rel.getSlave_table_id()).getName(), param.getAliasMap().get(rel.getSlave_table_id()));

            // 主字段,函数包裹
            String masterColumn = String.format(FORMAT_PREFFIX_FIELD, param.getAliasMap().get(rel.getMaster_table_id()), rel.getMaster_column());
            masterColumn = joinManager.renderByRules(masterColumn, param.getMasterTableRelRuleMap().get(rel.getId()));

            // 从字段，函数包裹
            String slaveColumn = String.format(FORMAT_PREFFIX_FIELD, param.getAliasMap().get(rel.getSlave_table_id()), rel.getSlave_column());
            slaveColumn = joinManager.renderByRules(slaveColumn, param.getSlaveTableRelRuleMap().get(rel.getId()));

            relSql.append(String.format(" %s %s %s on %s=%s ", i == 0 ? masterTable : "", LEFT_JOIN, slaveTable, masterColumn, slaveColumn));
            i++;
        }

        if (StringUtils.isEmpty(relSql)) {
            String masterTable = String.format(FORMAT_TABLE_ALIAS, param.getRelMap().get(param.getSrcTable().getId()).getName(), param.getAliasMap().get(param.getSrcTable().getId()));

            relSql.append(masterTable);
        }

        // where语句
        StringBuffer whereSql = new StringBuffer(WHERE);
        for (EtlTableFilterModel filter : param.getFilters()) {
            whereSql.append(buildWhereSql(param.getAliasMap().get(filter.getEtl_table_id()), filter));
        }

        // orderby语句
        StringBuffer orderbySql = new StringBuffer();
        for (EtlTableOrderbyModel orderby : param.getOrderbys()) {
            orderbySql.append(buildOrderBy(param.getAliasMap().get(orderby.getEtl_table_id()), orderby));
        }


        String result = String.format(FORMAT_SELECT_SQL, sql, relSql, whereSql, orderbySql);

        // 分页语句
        result = buildPaginationSql(result, param.getOffset(), param.getFetch_max_count());

        System.out.println(result);
        return result;
    }

    @Override
    public String buildCount(BuildSqlParam param) {
        // join语句
        int i = 0;
        StringBuffer relSql = new StringBuffer();
        JoinManager joinManager = JoinManager.getInstance(manager, param);
        for (EtlTableRelModel rel : param.getRels()) {

            // 检查字段关联合法性
            joinManager.check(this, rel);

            String masterTable = String.format(FORMAT_TABLE_ALIAS, param.getRelMap().get(rel.getMaster_table_id()).getName(), param.getAliasMap().get(rel.getMaster_table_id()));

            String slaveTable = String.format(FORMAT_TABLE_ALIAS, param.getRelMap().get(rel.getSlave_table_id()).getName(), param.getAliasMap().get(rel.getSlave_table_id()));

            // 主字段,函数包裹
            String masterColumn = String.format(FORMAT_PREFFIX_FIELD, param.getAliasMap().get(rel.getMaster_table_id()), rel.getMaster_column());
            masterColumn = joinManager.renderByRules(masterColumn, param.getMasterTableRelRuleMap().get(rel.getId()));

            // 从字段，函数包裹
            String slaveColumn = String.format(FORMAT_PREFFIX_FIELD, param.getAliasMap().get(rel.getSlave_table_id()), rel.getSlave_column());
            slaveColumn = joinManager.renderByRules(slaveColumn, param.getSlaveTableRelRuleMap().get(rel.getId()));

            relSql.append(String.format(" %s %s %s on %s=%s ", i == 0 ? masterTable : "", LEFT_JOIN, slaveTable, masterColumn, slaveColumn));
            i++;
        }

        if (StringUtils.isEmpty(relSql)) {
            String masterTable = String.format(FORMAT_TABLE_ALIAS, param.getRelMap().get(param.getSrcTable().getId()).getName(), param.getAliasMap().get(param.getSrcTable().getId()));

            relSql.append(masterTable);
        }

        // where语句
        StringBuffer whereSql = new StringBuffer(WHERE);
        for (EtlTableFilterModel filter : param.getFilters()) {
            whereSql.append(buildWhereSql(param.getAliasMap().get(filter.getEtl_table_id()), filter));
        }

        // orderby语句
        StringBuffer orderbySql = new StringBuffer();
        for (EtlTableOrderbyModel orderby : param.getOrderbys()) {
            orderbySql.append(buildOrderBy(param.getAliasMap().get(orderby.getEtl_table_id()), orderby));
        }

        String result = String.format(FORMAT_COUNT_SQL, relSql, whereSql);

        logger.info("查询总数sql："+result);
        return result;
    }

    @Override
    public String buildInsert(EtlTableModel table, Map<String, ColumnDesc> fieldData) {
        String fieldSql = "";
        String valueSql = "";
        StringBuffer fields = new StringBuffer();
        StringBuffer values = new StringBuffer();

        for (Map.Entry<String, ColumnDesc> entry : fieldData.entrySet()) {
            Object obj = entry.getValue().getObj();
            if (obj == null) {
                continue;
            }
            fields.append(entry.getKey()).append(COMMA);
            if (entry.getValue().isNumberType()) {
                values.append(obj.toString()).append(COMMA);
            } else if (entry.getValue().isDateType()) {
                Date date = (Date) obj;
                values.append(" to_date(").append(SINGLE_QUOTE).append(DateUtil.toString(date)).append(SINGLE_QUOTE).append(",'yyyy-mm-dd hh24:mi:ss')").append(COMMA);
            } else {
                values.append(SINGLE_QUOTE).append(obj.toString()).append(SINGLE_QUOTE).append(COMMA);
            }

        }
        if (StringUtils.isNotEmpty(fields) && fields.toString().endsWith(COMMA)) {
            fieldSql = fields.substring(0, fields.length() - 1);
        }
        if (StringUtils.isNotEmpty(values) && values.toString().endsWith(COMMA)) {
            valueSql = values.substring(0, values.length() - 1);
        }

        return String.format(FORMAT_INSERT_SQL, getTableName(table), fieldSql, valueSql);

    }

    @Override
    public String buildInsertSelect(EtlTableModel table, String targerTableName, Map<String, String> fields) {
        return null;
    }
}
